package cn.com.lms.business.exam.service;

import cn.com.lms.business.core.constant.ErrorEnum;

import cn.com.lms.business.exam.persistence.entity.QuestionCategory;
import cn.com.lms.business.exam.persistence.entity.QuestionSubject;
import cn.com.lms.business.exam.persistence.repository.QuestionCategoryRepository;


import com.bnzj.core.exception.BusinessException;
import com.bnzj.core.persistence.BaseService;
import com.bnzj.core.persistence.query.CompareExpression;
import com.bnzj.core.persistence.query.CompareType;
import com.bnzj.core.persistence.query.IExpression;


import com.bnzj.core.persistence.query.QueryHelpBean;
import com.bnzj.core.util.BeanUtils;
import com.bnzj.core.util.FbConstant;
import com.bnzj.core.web.util.WebUtils;

import org.hibernate.annotations.DynamicUpdate;
import org.hibernate.internal.util.StringHelper;
import org.springframework.beans.BeanWrapper;
import org.springframework.beans.BeanWrapperImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.beans.PropertyDescriptor;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class QuestionCategoryService extends BaseService<QuestionCategoryRepository, QuestionCategory, Long> {

    @Autowired
    QuestionService questionService;

    public static QueryHelpBean getQueryHelpBean() {
        String selectSQL = "select *";
        String whereSQL = " from bnz_exam_question_category where 1=1 ";
        QueryHelpBean queryBean = new QueryHelpBean(selectSQL + whereSQL, "select count(1)" + whereSQL, QuestionCategory.class);
        return queryBean;
    }


    /**
     * 分类树结构
     *
     * @return
     */
    public List<QuestionCategory> getMenuTree() {
        List<QuestionCategory> generateTreeMenu = repository.findAll(Sort.by(Sort.Direction.ASC, "id"));
        List<QuestionCategory> questionCategories = generateTreeMenu(generateTreeMenu);
        return questionCategories;
    }

    private List<QuestionCategory> generateTreeMenu(List<QuestionCategory> treeNodes) {
        List<QuestionCategory> rootNodes = treeNodes.stream().filter(node -> node.getIsDelete() == false && QuestionCategory.getRoot().getId().equals(node.getParentId())).collect(Collectors.toList());
        rootNodes.forEach(root -> findChildren(root, treeNodes));
        return rootNodes;
    }

    private void findChildren(QuestionCategory root, List<QuestionCategory> treeNodes) {
        List<QuestionCategory> children = treeNodes.stream().filter(node -> node.getIsDelete() == false && root.getId().equals(node.getParentId())).collect(Collectors.toList());
        root.setChildren(children);
        if (children != null) {
            children.forEach(child -> findChildren(child, treeNodes));
        }
    }

    /**
     * 查找 所有树子分类
     *
     * @param id
     * @return
     */
    public List<Long> findChildrenIds(Long id) {
        QuestionCategory root=null;
        if(id==0){
             root=QuestionCategory.getRoot();
        }else {
            Optional<QuestionCategory> qestionCategoryOpt = findById(id);
            if (!qestionCategoryOpt.isPresent()) {
                throw new BusinessException(ErrorEnum.RECORD_NOT_EXIST.getMessage(), "" + ErrorEnum.RECORD_NOT_EXIST.getCode());
            }
             root = qestionCategoryOpt.get();
        }
        List<QuestionCategory> generateTreeMenu = repository.findAll(Sort.by(Sort.Direction.ASC, "id"));
        List<Long> childrenIds = new ArrayList<>();
        this.setChildrenIds(root, generateTreeMenu, childrenIds);
        return childrenIds;
    }

    /**
     * 查找分类的题库总数
     *
     * @param ids
     * @return
     */
    public Long findTotalQuestionByIds(List<Long> ids) {
        Pageable pageable = WebUtils.initPage("1", "10", Sort.by(Sort.Direction.DESC, "create_time"));
        QueryHelpBean queryHelpBean = questionService.getQueryHelpBean("");
        queryHelpBean.setPageable(pageable);
        //根据题目名称，模糊搜索
        if(!CollectionUtils.isEmpty(ids)) {
            IExpression orCondition1 = CompareExpression.build("eq.category_id", CompareType.in, ids);
            queryHelpBean.addWhere(orCondition1);
        }
        IExpression andCondition2 = CompareExpression.build("eq.is_delete", CompareType.equal, false);
        queryHelpBean.addWhere(andCondition2);
        Page<QuestionSubject> all = questionService.findAll(queryHelpBean);
        return all.getTotalElements();
    }

    @Transactional(rollbackFor = Exception.class)
    public void deleteByIds(List<Long> list) {
        deleteAll(list);
    }

    public int updateIsDelete(Boolean isDelete, List<Long> id) {
        return repository.updateIsDelete(isDelete, id);
    }


    private void setChildrenIds(QuestionCategory root, List<QuestionCategory> generateTreeMenu, List<Long> childrenIds) {
        List<QuestionCategory> children = generateTreeMenu.stream().filter(item -> item.getIsDelete()==false &&  root.getId().equals(item.getParentId())).collect(Collectors.toList());
        if (children != null) {
            children.stream().forEach(child -> {
                childrenIds.add(child.getId());
                setChildrenIds(child, generateTreeMenu, childrenIds);
            });
        }
    }


    public QuestionCategory updateQuestionCategory(QuestionCategory questionCategory) {
        //1.获取最新对象
        Optional<QuestionCategory> questionCategoryOpt = findById(questionCategory.getId());
        if (!questionCategoryOpt.isPresent()) {
            throw new BusinessException(ErrorEnum.RECORD_NOT_EXIST.getMessage(), "" + ErrorEnum.RECORD_NOT_EXIST.getCode());
        }
        QuestionCategory target = questionCategoryOpt.get();
        //2.将非空属性覆盖到最新对象
//        BeanUtils.copyPropertiesIgnoreNull(questionCategory, target);
        BeanUtils.copyProperties(questionCategory, target);
        super.save(target);
        return target;

    }


}
